package com.atguigu.java8.optional;

import com.atguigu.java8.lambda.Employee;
import org.junit.Test;

import java.util.Optional;

public class TestOptional {

    @Test
    public void test1() {
        // Optional.of(T t)：创建一个Optional实例
        Optional<Employee> optional = Optional.of(new Employee());
        Employee employee = optional.get();
        System.out.println(employee);

        // 第18行代码报错：java.lang.NullPointerException
        Optional<Employee> optional1 = Optional.of(null);
        Employee employee1 = optional1.get();
        System.out.println(employee1);
    }

    @Test
    public void test2() {
        // Optional.empty()：创建一个空的Optional实例
        Optional<Object> empty = Optional.empty();
        // 第27行代码报错：java.util.NoSuchElementException: No value present
        Object o = empty.get();
        System.out.println(o);
    }

    @Test
    public void test3() {
        // Optional.ofNullable(T t)：若t不为null，创建Optional实例，否则创建空实例
        Optional<Employee> optional = Optional.ofNullable(new Employee());
        System.out.println(optional.get());

        Optional<Employee> optional1 = Optional.ofNullable(null);
        // 第39行代码报错：java.util.NoSuchElementException: No value present
        // System.out.println(optional1.get());

        // 安全访问
        // isPresent()：判断是否包含值
        if (optional1.isPresent()) {
            System.out.println(optional1.get());
        }

        // orElse(T t)：如果调用对象包含值，返回该值，否则返回t
        Employee employee = optional1.orElse(new Employee("allen", 20, 3333.33, Employee.Status.BUSY));
        System.out.println(employee);
    }

    @Test
    public void test4() {
        // orElseGet(Supplier s)：如果调用对象包含值，返回该值，否则返回s获取的值
        Optional<Employee> optional = Optional.ofNullable(null);
        Employee employee = optional.orElseGet(Employee::new);
        System.out.println(employee);
    }

    @Test
    public void test5() {
        // map(Function f)：如果有值对其处理，并返回处理后的Optional，否则返回Optional.empty()
        Optional<Employee> optional = Optional.ofNullable(new Employee("allen", 22));
        Optional<String> optional1 = optional.map(Employee::getName);
        System.out.println(optional1.get());

        // flatMap(Function mapper)：与map类似，要求返回值必须是Optional
        optional = Optional.ofNullable(new Employee("allen", 22, 5555.55, Employee.Status.BUSY));
        Optional<String> optional2 = optional.flatMap(e -> Optional.ofNullable(e.getStatus()).map(Enum::name));
        System.out.println(optional2.orElse("default"));

        optional = Optional.ofNullable(new Employee("allen", 22));
        Optional<String> optional3 = optional.flatMap(e -> Optional.ofNullable(e.getStatus()).map(Enum::name));
        System.out.println(optional3.orElse("default"));
    }

    // 需求：获取男人的女神名
    @Test
    public void test6() {
        Man man = new Man();
        // 第83行代码error:java.lang.NullPointerException
        // String goddessName = getGoddessName(man);
        // System.out.println(goddessName);

        String goddessName2 = getGoddessName2(man);
        System.out.println(goddessName2);
    }

    private String getGoddessName(Man man) {
        return man.getGoddess().getName();
    }

    // 防御性编程
    private String getGoddessName2(Man man) {
        if (man != null) {
            Goddess goddess = man.getGoddess();
            if (goddess != null) {
                return goddess.getName();
            }
        }
        return "none";
    }

    // 需求：获取男人的女神名
    @Test
    public void test7() {
        Optional<NewMan> optional = Optional.ofNullable(null);
        String goddessName3 = getGoddessName3(optional);
        System.out.println(goddessName3);

        optional = Optional.ofNullable(new NewMan());
        goddessName3 = getGoddessName3(optional);
        System.out.println(goddessName3);

        Optional<Goddess> goddess = Optional.ofNullable(new Goddess("aaa"));
        optional = Optional.ofNullable(new NewMan(goddess));
        goddessName3 = getGoddessName3(optional);
        System.out.println(goddessName3);
    }

    private String getGoddessName3(Optional<NewMan> optionalNewMan) {
        return optionalNewMan.orElse(new NewMan()).getGoddess().map(Goddess::getName).orElse("none");
    }

}
